package com.alinesno.cloud.common.core.dubbo.filter;

import java.lang.reflect.Method;

import org.apache.dubbo.common.constants.CommonConstants;
import org.apache.dubbo.common.extension.Activate;
import org.apache.dubbo.rpc.Filter;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.Result;
import org.apache.dubbo.rpc.RpcContext;
import org.apache.dubbo.rpc.RpcException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alinesno.cloud.common.core.annotations.TenantMethod;
import com.alinesno.cloud.common.core.dubbo.BaseFilter;
import com.alinesno.cloud.common.facade.wrapper.RestWrapper;

/**
 * Dubbo服务拦截器，用于权限，调用日志等拦截，用于全局拦截
 * 
 * @author WeiXiaoJin
 * @since 2019年9月19日 上午7:23:53
 */
@Activate(group = { CommonConstants.PROVIDER }, order = -2000)
public class DubboTenantProviderFilter extends BaseFilter implements Filter {

	@SuppressWarnings("unused")
	private static final Logger log = LoggerFactory.getLogger(DubboTenantProviderFilter.class);

	@Override
	public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {

		RpcContext ctx = attachment(invoker, invocation);

		String applicationId = ctx.getAttachment(APPLICATION_ID);
		String operatorId = ctx.getAttachment(OPERATOR_ID);
		
		Method[] ms = invoker.getInterface().getMethods() ; 
		System.out.println(invocation.getMethodName());
		
		for(Method m : ms) {
			if(m.getName().equals(invocation.getMethodName())) {
				TenantMethod tenantMethod = m.getAnnotation(TenantMethod.class) ; 
				
				if(tenantMethod != null) {
					
					Object[] args = invocation.getArguments() ; 
					
					for(int i = 0 ; i < args.length ; i ++) {
						Object a = args[i] ; 
						if(a instanceof RestWrapper) {  // 参数权限
							RestWrapper r = (RestWrapper) a ; 
							if(!r.isRemoveApplication()) {
								r.eq(APPLICATION_ID, applicationId) ; 
							}
							r.eq(OPERATOR_ID, operatorId) ; 
							
							args[i] = r ; // 重新赋值 
						}
					}
					
				}
			}
		}
			
		Result result = invoker.invoke(invocation);
		return result;
	}

}
